use crate::rating::*;
use crate::rule::*;

#[derive(Debug, PartialEq)]
pub enum WorkflowResult {
    Accept,
    Reject,
    Jump(String)
}

#[derive(Debug, PartialEq)]
pub struct Workflow {
    name: String,
    rules: Vec<Rule>,
}

impl Workflow {
    pub fn new(name: String, rules: Vec<Rule>) -> Self {
        Self { name, rules }
    }

    pub fn query(&self, rating: &Rating) -> WorkflowResult {
        for rule in self.rules.iter() {
            let res = rule.query(rating);
            match res {
                RuleResult::Accept => return WorkflowResult::Accept,
                RuleResult::Reject => return WorkflowResult::Reject,
                RuleResult::Next   => continue,
                RuleResult::Jump(next)  => return WorkflowResult::Jump(next),
            }
        }
        panic!("workflow {} can't get a vaild result.", self.name);
    }
}

impl From<&str> for Workflow {
    fn from(value: &str) -> Self {
        // px{a<2006:qkq,m>2090:A,rfg}
        let left_pos = value.find('{').expect("Error workflow string");
        let name = value[..left_pos].to_string();

        Self {
            name,
            rules: value[left_pos+1..value.len()-1].split(',').map(|rule_str| -> Rule {
                rule_str.into()
            }).collect()
        }
    }
}

